Introduction to useRef and Creating Component Variables Instead of useState
When developing with React, you'll often find yourself managing state within your components using useState. While useState is incredibly useful, there are situations where using useRef might be a better option. This guide will introduce you to useRef, explain when and why you might choose it over useState, and walk you through creating component variables that don’t trigger re-renders, improving your application's performance and usability.
What is useRef?
useRef is a hook in React that returns a mutable object. This object has a .current property, which you can set to any value. Unlike useState, updating this .current property does not cause a component to re-render. This makes useRef perfect for storing values that don't directly impact the visual output of your component, such as:
- DOM elements
- Timers
- Previous values
- Persistent values across renders
Basic Usage of useRef
Let's start with a simple example where we use useRef to keep track of a DOM element:
import React, { useRef, useEffect } from 'react';
function FocusInput() {
  // Create a ref to store the input element
  const inputRef = useRef(null);
  // Focus the input element when the component mounts
  useEffect(() => {
    inputRef.current.focus(); // Access the DOM node through the ref
  }, []);
  return (
    <input ref={inputRef} type="text" placeholder="Focus me on mount!" />
  );
}
export default FocusInput;
When to Use useRef Instead of useState
There are specific scenarios where useRef is more appropriate than useState:
- 
Storing Non-Render-Related Data: If you need to store data that doesn’t affect the UI, useRefis your go-to. For example, tracking the number of times a button is clicked within a session but not displaying that count in the UI.function ClickTracker() {
 const clickCount = useRef(0); // Initial value of 0
 const handleClick = () => {
 clickCount.current += 1; // Increment the count
 console.log(`Button clicked ${clickCount.current} times`);
 };
 return (
 <button onClick={handleClick}>
 Click me
 </button>
 );
 }Here, clickCountis incremented with every click, but since it’s not used in rendering, the component doesn’t re-render unnecessarily.
- 
Referencing DOM Elements: As shown in the first example, useRefis ideal for referencing DOM elements and performing actions like focusing or measuring dimensions.
- 
Storing Mutable Objects: If you’re dealing with objects or arrays that you need to persist across renders without triggering a re-render, useRefis appropriate.
- 
Avoiding Re-Renders with Stable References: Using useRefcan also help maintain stable references to objects or functions between renders, especially when passing them as dependencies touseEffector callbacks.
Creating Component Variables with useRef
Consider a situation where you want to implement a simple timer in your component. Using useRef, you can store a reference to the timer ID without triggering re-renders.
import React, { useRef, useState } from 'react';
function Timer() {
  const [seconds, setSeconds] = useState(0);
  const timerId = useRef(null); // Ref to store the timer ID
  const startTimer = () => {
    if (timerId.current) return; // Prevent multiple timers
    timerId.current = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);
  };
  const stopTimer = () => {
    clearInterval(timerId.current);
    timerId.current = null; // Reset the ref
  };
  return (
    <div>
      <p>Timer: {seconds} seconds</p>
      <button onClick={startTimer}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}
export default Timer;
In this example:
- useRefis used to store the timer ID, which doesn’t need to trigger a re-render when it changes.
- useStatemanages the- seconds, which needs to be re-rendered each second.
Key Points to Remember
- useRefdoes not trigger re-renders: Updating the- .currentproperty will not cause the component to re-render.
- Perfect for storing mutable objects: Use useReffor values that need to persist across renders without affecting the UI.
- Great for referencing DOM elements: useRefis a handy way to directly access and manipulate DOM nodes.
Further Reading
- React Refs
- Managing State vs. Refs
- useState vs. useRef
- React Performance Optimization
Summary
useRef is a powerful React hook for creating mutable references to values or DOM elements that persist across renders without causing re-renders. It's particularly useful for storing non-UI related data, maintaining stable references, and managing DOM elements. Understanding when to use useRef instead of useState is key to writing efficient and effective React components.